package com.neulogistics.contrib.warehouse.api.application.query;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.neulogistics.contrib.warehouse.api.application.converter.WarehousePOVMConverter;
import com.neulogistics.contrib.warehouse.api.application.converter.WarehouseQueryPOConverter;
import com.neulogistics.contrib.warehouse.api.application.converter.WarehouseTreePOVMConverter;
import com.neulogistics.contrib.warehouse.api.application.viewmodel.WarehouseTreeViewModel;
import com.neulogistics.contrib.warehouse.api.application.viewmodel.WarehouseViewModel;
import com.neulogistics.contrib.warehouse.domain.model.valueobject.Address;
import com.neulogistics.contrib.warehouse.infrastructure.persistence.orm.po.WarehousePO;
import com.neulogistics.contrib.warehouse.infrastructure.persistence.orm.service.IWarehousePOService;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
public class WarehouseQueryService implements IWarehouseQueryService {

    @Resource
    private IWarehousePOService warehousePOService;

    @Override
    public WarehouseViewModel getById(Integer id) {
        WarehousePO warehousePO = warehousePOService.getById(id);
        WarehouseViewModel warehouseViewModel = WarehousePOVMConverter.POToVM(warehousePO);
        return warehouseViewModel;
    }

    @Override
    public List<WarehouseTreeViewModel> list() {
        List<WarehousePO> poList = warehousePOService.list();
        List<WarehouseTreeViewModel> viewModelList = poList
                .parallelStream()
                .map(WarehouseTreePOVMConverter::POToVM)
                .collect(Collectors.toList());
        return viewModelList;
    }

    @Override
    public Page<WarehouseViewModel> page(WarehouseQuery warehouseQuery) {
        // 取出条件
        WarehousePO warehousePO = WarehouseQueryPOConverter.queryToPO(warehouseQuery);
        long current = warehouseQuery.getPageNum();
        long pageSize = warehouseQuery.getPageSize();

        // 查询
        QueryWrapper<WarehousePO> queryWrapper = new QueryWrapper<>(warehousePO);
        Page<WarehousePO> page = warehousePOService.page(new Page<>(current, pageSize), queryWrapper);

        // 构造结果
        Page<WarehouseViewModel> viewModelPage = new Page<>(current, pageSize);
        List<WarehouseViewModel> viewModelList = page.getRecords().stream()
                .map(WarehousePOVMConverter::POToVM).collect(Collectors.toList());
        viewModelPage.setRecords(viewModelList);
        viewModelPage.setTotal(page.getTotal());
        return viewModelPage;
    }

    /**
     * 返回所给地址附近的中心库房，和分站库房
     * 以map形式返回，key为 center、substation
     * @param address
     * @return
     */
    @Override
    public Map<String, List> getRecommendedWarehouse(Address address) {
        // 先按照省获取中心库房，如果没有则获取所有中心库房
        List<WarehousePO> centerWarehouses = warehousePOService.getCenterWarehousesByProvince(address.getProvince());
        if (centerWarehouses.isEmpty()){
            LambdaQueryWrapper<WarehousePO> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(WarehousePO::getWarehouseLevel, 0);
            centerWarehouses = warehousePOService.list(queryWrapper);
        }

        // 再按照省份获取分站库房，能下单说明区内一定有分站库房
        List<WarehousePO> subWarehouses = warehousePOService.getSubWarehousesByProvince(address.getProvince());

        // 对分站库房进行过滤筛选
        subWarehouses = subWarehouses.stream().filter((p) -> {
            String city = p.getWarehouseAddress().get("city", String.class);
            String zone = p.getWarehouseAddress().get("zone", String.class);
            return address.getCity().equals(city) && address.getZone().equals(zone);
        }).collect(Collectors.toList());

        HashMap<String, List> result = new HashMap<>();
        result.put("center", centerWarehouses);
        result.put("substation", subWarehouses);

        return result;
    }

    @Override
    public List<Integer> getAllWarehouseId() {
        List<WarehousePO> warehousePOS = warehousePOService.list();
        List<Integer> ids = warehousePOS.stream().map(WarehousePO::getWarehouseId).collect(Collectors.toList());
        return ids;
    }
}
